package com.wtwd.campus.netty;


import com.wtwd.campus.common.Constants;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 消息解码
 */
public class MessageDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
                          List<Object> out) throws Exception {
        // 可读长度必须大于基本长度
        if (buffer.readableBytes() >= 4) {
            if (buffer.readableBytes() > 2048) {    // 防止socket字节流攻击;防止，客户端传来的数据过大;因为，太大的数据，是不合理的
                buffer.skipBytes(buffer.readableBytes());
            }
            int beginReader;  // 包头开始的位置
            while (true){  // 读到协议开始的位置就跳出循环，然后开始读取数据；正常来说第一个就是协议开始数据
                // 记录包头开始的位置
                beginReader = buffer.readerIndex();
                // 标记当前读的位置，如果是读到了开头，则会跳出循环；因此可以保证最后标记的是开头的前一位
                buffer.markReaderIndex();
                // 解析每个字节，直到读到了开始标志位
                String beginHexString = readData(buffer,1);
                if(beginHexString.equalsIgnoreCase("*")){  // 判断下一个是否为7E，头尾一样，避免读到尾
                    buffer.readerIndex(beginReader);
                    break;
                }
                // 未读到包头，略过一个字节
                // 每次略过，一个字节，去读取，包头信息的开始标记
                buffer.resetReaderIndex();
                buffer.readBytes(2);

                // 当剩下的长度不足一包时，应该return;放弃本次读的操作，等待下一包的到来
                if (buffer.readableBytes() < 30) {
                    return;
                }
            }
            // 读到了开头，就开始读取数据
            StringBuffer stringBuffer = new StringBuffer();
            // 读取开头
            buffer.markReaderIndex();
            String contentBeginHexString = readData(buffer,1);
            stringBuffer.append(contentBeginHexString);
            while(true){
                // 标记一下读取的位置
                buffer.markReaderIndex();
                String hexStringContent = readData(buffer,1);
                stringBuffer.append(hexStringContent);
                if(hexStringContent.equalsIgnoreCase("#")){  // 读到了结束
                    break;
                }
            }
            out.add(stringBuffer);
        }
    }

    public String readData(ByteBuf buffer,int length) throws UnsupportedEncodingException {
        byte[] data = new byte[length];
        buffer.readBytes(data);
        String hexStringData = new String(data, Constants.DEVICE_DATA_CHARSET);
        return hexStringData;
    }

}
